package com.android.myexoplayer;

import android.app.Fragment;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.LoopingMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;

import java.lang.ref.WeakReference;


public class MyExoPlayerFragment extends Fragment implements View.OnClickListener {
    private static final int BOTTOM_RL = 1;
    public static final int DECOR_VIEW = 2;
    private static final int click_moving = 5;
    private SimpleExoPlayerView simpleExoPlayerView;
    private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
    private SimpleExoPlayer player;
    private DefaultTrackSelector trackSelector;
    public HomeListener mHomeWatcher;
    private EventLogger eventLogger;
    private RelativeLayout bottomRL;
    public ImageView fullscreen;
    public ExoHandler exoHandler;
    private MyExoPlayerPresenter myExoPlayerPresenter;
    private boolean isClick;
    private boolean mIsLand = false; // 是否是横屏
    private boolean mClickLand = true; // 点击进入横屏
    private boolean mClickPort = true; // 点击进入竖屏

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_myexoplayer, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        exoHandler = new ExoHandler(this);
        myExoPlayerPresenter = new MyExoPlayerPresenter();
        myExoPlayerPresenter.verifyStoragePermissions(getActivity());
        myExoPlayerPresenter.registerHomeListener(this);
        orientationEventListener();
        myExoPlayerPresenter.controlDecorView(this);
        simpleExoPlayerView = (SimpleExoPlayerView) view.findViewById(R.id.player_view);
        bottomRL = (RelativeLayout) view.findViewById(R.id.bottomRL);
        bottomRL.setAlpha(0.5f);
        fullscreen = (ImageView) view.findViewById(R.id.fullscreen);
        fullscreen.setOnClickListener(this);
        simpleExoPlayerView.setOnTouchListener(new ExoPlayerOnTouchListener());
        initializePlayer();
    }

    private void initializePlayer() {
        // 创建轨道选择工厂
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
        //创建轨道选择器实例 TrackSelector 选择MediaSource中的轨道（Track）交由TrackRenderer负责渲染,这里包括音频轨道和视频轨道。
        trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
        //LoadControl 用来控制缓存的，当媒体需要更多缓存的时候，LoadControl 来控制缓存的数量，当播放器被创建时，LoadControl 会被注入。
//        LoadControl loadControl = new DefaultLoadControl();
        //使用ExoPlayerFactory 创建一个ExoPlayer 实例
//        SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
        player = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector);
        simpleExoPlayerView.setPlayer(player);  //把player渲染在View上
        simpleExoPlayerView.setUseController(false);  //隐藏播放精度条等按钮
        player.addListener(new ExoPlayerEventListener());
        eventLogger = new EventLogger(trackSelector);
        player.setAudioDebugListener(eventLogger);
        player.setVideoDebugListener(eventLogger);
        player.setMetadataOutput(eventLogger);

        DataSource.Factory mediaDataSourceFactory = buildDataSourceFactory(true);
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
//        Uri uri = Uri.parse("https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/video-avc-baseline-480.mp4");
        Uri uri = Uri.parse("file:///android_asset/left_base_forefinger.mp4");
        // 创建视频源
        MediaSource videoSource = new ExtractorMediaSource(uri, mediaDataSourceFactory, extractorsFactory, null, null);
        //循环source
        LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);
        player.prepare(loopingSource);
        View surfaceView = simpleExoPlayerView.getVideoSurfaceView();
        if (surfaceView instanceof SurfaceView) {
            ((SurfaceView) surfaceView).getHolder().addCallback(new SurfaceCallback());
        } else {
            player.setPlayWhenReady(true); //开始 和 暂停
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (player == null) {
            initializePlayer();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (exoHandler != null) {
            exoHandler.removeCallbacksAndMessages(null);
        }
        if (mHomeWatcher != null) {
            mHomeWatcher.stopWatch();
        }
        releasePlayer();
    }


    /**
     * 释放资源
     */
    public void releasePlayer() {
        if (player != null) {
            player.release();
            player = null;
            trackSelector = null;
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        myExoPlayerPresenter.configurationChanged(this);
    }


    private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
        return ((ExoPlayerApplication) getActivity().getApplication())
                .buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
    }

    /**
     * 点击事件
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.fullscreen:
                if (exoHandler.hasMessages(BOTTOM_RL)) {
                    exoHandler.removeMessages(BOTTOM_RL);
                    exoHandler.sendEmptyMessageDelayed(BOTTOM_RL, 3000);
                }
                isClick = true;
                if (this.getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
                    this.getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    mIsLand = true;
                    mClickLand = false;
                } else {
                    this.getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    mIsLand = false;
                    mClickPort = false;
                }
                break;
        }
    }

    /**
     * 屏幕旋转监听
     */
    private final void orientationEventListener() {
        new OrientationEventListener(getActivity()) {
            @Override
            public void onOrientationChanged(int rotation) {
                // 设置竖屏
                if (((rotation >= 0) && (rotation <= 30)) || (rotation >= 330)) {
                    if (isClick) {
                        if (mIsLand && !mClickLand) {
                            return;
                        } else {
                            mClickPort = true;
                            isClick = false;
                            mIsLand = false;
                        }
                    } else {
                        if (mIsLand) {
                            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                            mIsLand = false;
                            isClick = false;
                        }
                    }
                }
                // 设置横屏
                else if (((rotation >= 230) && (rotation <= 310))) {
                    if (isClick) {
                        if (!mIsLand && !mClickPort) {
                            return;
                        } else {
                            mClickLand = true;
                            isClick = false;
                            mIsLand = true;
                        }
                    } else {
                        if (!mIsLand) {
                            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                            mIsLand = true;
                            isClick = false;
                        }
                    }
                }
            }
        }.enable();
    }


    /**
     * 视频播放器的状态回调
     */
    class ExoPlayerEventListener implements Player.EventListener {

        @Override
        public void onTimelineChanged(Timeline timeline, Object manifest) {

        }

        @Override
        public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

        }

        @Override
        public void onLoadingChanged(boolean isLoading) {

        }

        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            switch (playbackState) {
                case PlaybackState.STATE_PLAYING:
                    //初始化播放点击事件并设置总时长
                    System.out.println("1111111111111111播放状态: 准备 playing");
                    break;
                case PlaybackState.STATE_BUFFERING:
                    System.out.println("111111111111111111111111播放状态: 缓存完成 playing");
                    break;
                case PlaybackState.STATE_CONNECTING:
                    System.out.println("11111111111111111111111播放状态: 连接 CONNECTING");
                    break;
                case PlaybackState.STATE_ERROR://错误
                    System.out.println("111111111111111111111播放状态: 错误 STATE_ERROR");
                    break;
                case PlaybackState.STATE_FAST_FORWARDING:
                    System.out.println("播放状态: 快速传递");
                    break;

                case PlaybackState.STATE_NONE:
                    System.out.println("播放状态: 无 STATE_NONE");
                    break;
                case PlaybackState.STATE_PAUSED:
                    System.out.println("播放状态: 暂停 PAUSED");
                    break;
                case PlaybackState.STATE_REWINDING:
                    System.out.println("播放状态: 倒回 REWINDING");
                    break;
                case PlaybackState.STATE_SKIPPING_TO_NEXT:
                    System.out.println("播放状态: 跳到下一个");
                    break;
                case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
                    System.out.println("播放状态: 跳到上一个");
                    break;
                case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM:
                    System.out.println("播放状态: 跳到指定的Item");
                    break;
                case PlaybackState.STATE_STOPPED:
                    System.out.println("播放状态: 停止的 STATE_STOPPED");
                    break;
            }
        }


        @Override
        public void onRepeatModeChanged(int repeatMode) {

        }

        @Override
        public void onPlayerError(ExoPlaybackException error) {

        }

        @Override
        public void onPositionDiscontinuity() {

        }

        @Override
        public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

        }
    }

    /**
     * 触屏点击事件
     */
    class ExoPlayerOnTouchListener implements View.OnTouchListener {
        float x = 0;
        float y = 0;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                x = event.getX();
                y = event.getY();
            } else if (event.getAction() == MotionEvent.ACTION_UP) { //点击事件
                if (x + click_moving > event.getX() && x - click_moving < event.getX() && y + click_moving > event.getY() && y - click_moving < event.getY()) {
                    if (bottomRL.getVisibility() == View.VISIBLE) {
                        bottomRL.setVisibility(View.GONE);
                        if (exoHandler.hasMessages(BOTTOM_RL)) {
                            exoHandler.removeMessages(BOTTOM_RL);
                        }
                    } else {
                        bottomRL.setVisibility(View.VISIBLE);
                        exoHandler.sendEmptyMessageDelayed(BOTTOM_RL, 3000);
                    }
                }
            }
            return true;
        }
    }

    /**
     * SurfaceView加载回调
     */
    class SurfaceCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            if (player != null) {
                player.setPlayWhenReady(true); //开始 和 暂停
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    }

    /**
     * handler
     */
    static class ExoHandler extends Handler {
        private final WeakReference<MyExoPlayerFragment> weakMyExoPlayerFragment;

        public ExoHandler(MyExoPlayerFragment fragment) {
            weakMyExoPlayerFragment = new WeakReference<MyExoPlayerFragment>(fragment);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MyExoPlayerFragment myExoPlayerFragment;
            if (weakMyExoPlayerFragment.get() == null) {
                return;
            } else {
                myExoPlayerFragment = weakMyExoPlayerFragment.get();
            }
            switch (msg.what) {
                case BOTTOM_RL:
                    if (myExoPlayerFragment.bottomRL != null) {
                        myExoPlayerFragment.bottomRL.setVisibility(View.GONE);
                    }
                    break;
                case DECOR_VIEW:
                    if (myExoPlayerFragment.myExoPlayerPresenter.decorView != null) {
                        myExoPlayerFragment.myExoPlayerPresenter.decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
                    }
                    break;
            }
        }
    }

}
